package ml.tewas.engine;

import java.util.HashMap;
import java.util.Map;

import javax.swing.JOptionPane;

import ml.tewas.commondata.ForceEnum;
import ml.tewas.commondata.ForceStruct;
import ml.tewas.commondata.ScenarioFinalStateEnum;
import ml.tewas.commondata.ThreatClassificationEnum;
import ml.tewas.commondata.ThreatEvaluationResultStruct;
import ml.tewas.commondata.ThreatStruct;
import ml.tewas.gui.DrawingCanvas;
import ml.tewas.util.Utilities;

public class Engine extends Thread {

	private long tickTime = 100;
	
	Map<Integer,Map<Integer,ThreatClassificationEnum>> classificationMap = new HashMap<Integer, Map<Integer,ThreatClassificationEnum>>();
	Map<Integer,Integer> targetMap = new HashMap<Integer, Integer>();
	Map<Integer,Map<Integer, ThreatEvaluationResultStruct>> resultMap = new HashMap<Integer, Map<Integer,ThreatEvaluationResultStruct>>();

	public Engine(long tickTime) {
		if (tickTime > this.tickTime)
			this.tickTime = tickTime;
	}

	public void run() {

		DrawingCanvas instance = DrawingCanvas.getInstance();
		int state;
		
		int workingMode = instance.getWorkingMode();
		while ((state = instance.getState()) == DrawingCanvas.PLAY
				|| state == DrawingCanvas.PAUSE) {

			if (state == DrawingCanvas.PAUSE)
				continue;
			try {
				Thread.sleep(tickTime);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			forceOperations(instance);
			int destroyCount = 0;
			for (ThreatStruct threat : instance.getThreatList()) {
				threat.tick();
				if(threat.isDestroyed())
					destroyCount++;
			}
			if(destroyCount == instance.getThreatList().size())
				instance.setState(DrawingCanvas.END_WIN);
			repaint(instance);
		}
		if (state == DrawingCanvas.END_WIN) {
			if (workingMode == DrawingCanvas.MANUEL_MODE) {
				JOptionPane.showMessageDialog(instance,
						"CONGRATULATIONS, AGENTS WON!");
			} else {
				instance.agentWin();
				instance.getForceList().get(1).save(ScenarioFinalStateEnum.AGENT_WIN);
			}
		} else if (state == DrawingCanvas.END_LOST) {
			if (workingMode == DrawingCanvas.MANUEL_MODE) {
				JOptionPane.showMessageDialog(instance, "SORRY, AGENTS LOST!");
			} else {
				instance.agentLost();
				instance.getForceList().get(1).save(ScenarioFinalStateEnum.AGENT_LOSE);
			}
		}
		instance.setState(DrawingCanvas.SCENARIO_END);
	}

	private void forceOperations(DrawingCanvas instance) {
		
		classificationMap.clear();
		targetMap.clear();
		resultMap.clear();
		for (ForceStruct force : instance.getForceList()) {
				classificationMap.put(force.getAgentID(), force.estimateClassification());
		}
		
		for (ForceStruct force : instance.getForceList()) {
			int agentID = force.getAgentID();
			if (agentID != Utilities.UNARMED_AGENT_ID) {
				Map<Integer, ThreatEvaluationResultStruct> qState = new HashMap<Integer, ThreatEvaluationResultStruct>();
				for (ThreatStruct threat : Utilities.filterThreats(instance.getThreatList())) {
					ThreatEvaluationResultStruct evalStruct = new ThreatEvaluationResultStruct();
					int threatID = threat.getThreatID();
					for (Integer key : classificationMap.keySet()) {
						int keyVal = key.intValue();
						if (keyVal == agentID) {
							evalStruct
									.setAgentOwnClassification(classificationMap
											.get(agentID).get(threatID));
						} else if (keyVal != Utilities.UNARMED_AGENT_ID) {
							evalStruct.putOtherAgentClassifications(
									ForceEnum.ARMEDAGENT, classificationMap
											.get(keyVal).get(threatID));
						} else {
							evalStruct.putOtherAgentClassifications(
									ForceEnum.UNARMED, classificationMap
											.get(keyVal).get(threatID));
						}
					}
					qState.put(threatID, evalStruct);
				}
				int targetThreat = force.getWeaponAssignedThreatID(qState);
				targetMap.put(agentID, targetThreat);
				resultMap.put(agentID, qState);
			}
		}
		for (ForceStruct force : instance.getForceList()) {
			int agentID = force.getAgentID();
			if (agentID != Utilities.UNARMED_AGENT_ID) {
				force.shoot(targetMap.get(agentID));
				for (Integer key : targetMap.keySet()) {
					if (key.intValue() != agentID) {
						force.setWeaponAssignedThreatIDForOtherAgent(resultMap
								.get(key), targetMap.get(key));
					}  
				}
			}
		}
	}

	private void repaint(DrawingCanvas instance) {
		instance.repaint();
	}

}
